#ifndef PIPE_H
#define PIPE_H
#include <unistd.h>
#include <fcntl.h>
#include "testbase.h"

class Pipe : public TestBase {
public:
    Pipe(int argc=0, char** argv=nullptr)
        : TestBase(argc, argv)
        , valid(!pipe(fd)) // // 0 or -1
        , abort(false)
    {
        if(!valid) return;
        th = std::thread(&Pipe::read, this);
        setNonBlocking(fd[0]); // 读fd设置为非阻塞 （阻塞模式下，退出需要先唤醒read）
    }

    ~Pipe() {
        if(!valid) return;
        if(th.joinable()) th.join();
        close(fd[0]);
        close(fd[1]);
    }

    void read() {
        char buf[1024]{};
        while(!abort) {
            int ret = ::read(fd[0], buf, 1024);
            if(ret > 0) {
                cout << "read : " << buf << endl;
                memset(buf, 0, 1024);
            }
        }
    }

    void write(const std::string& str) {
        int ret = ::write(fd[1], str.data(), str.size());
        if(ret > 0) puts("write succeed");
        else cout << "write fail, " <<  strerror(errno) << endl;
    }

    void test() override {
        if(!valid) {
            puts("test fail");
            return;
        }
        std::string str;
        while(!abort) {
            cout << "input data:";
            std::getline(cin, str);
            if(abort) break;
            write(str);
            std::this_thread::yield();
        }
    }

    void quit() {
        abort = true;
    }

private:
    int fd[2]; // 0读 1写
    std::thread th;
    bool valid;
    std::atomic_bool abort;
};
#endif // PIPE_H
